package com.augrain.microframework.core.util;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.List;

/**
 * json
 *
 * @author biaoy
 * @since 2025/10/25
 */
@Slf4j
public class JSONUtils {

    @Getter
    protected static ObjectMapper objectMapper = new ObjectMapper();

    static {
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略未知属性，而不返回失败
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); // 允许非标准的json格式：json字段名称可以不使用"包裹
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); // 允许非标准的json格式：json字段名称和字段值可以使用'包裹
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.registerModule(new JavaTimeModule());
    }

    /**
     * Object可以是POJO，也可以是Collection或数组。
     * 如果对象为Null, 返回"null".
     * 如果集合为空集合, 返回"[]".
     */
    public static String toJson(Object object) {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (IOException e) {
            log.error("to json exception", e);
            return null;
        }
    }

    /**
     * 反序列化POJO或简单Collection如List<String>.
     * <p>
     * 如果JSON字符串为Null或"null"字符串, 返回Null.
     * 如果JSON字符串为"[]", 返回空集合.
     * <p>
     * 如需反序列化复杂Collection如List<MyBean>, 请使用fromJson(String,JavaType)
     */
    public static <T> T fromJson(String jsonString, Class<T> clazz) {
        if (!StringUtils.hasText(jsonString)) {
            return null;
        }
        try {
            return objectMapper.readValue(jsonString, clazz);
        } catch (Exception e) {
            log.error("from json happen err", e);
            return null;
        }
    }

    public static <T> T fromJson(InputStream inputStream, Class<T> clazz) {
        try {
            return objectMapper.readValue(inputStream, clazz);
        } catch (IOException e) {
            log.error("from json happen err", e);
            return null;
        }
    }

    /**
     * 解析集合
     */
    public static <T> List<T> listFromJson(String jsonString, Class<T> clazz) {
        if (!StringUtils.hasText(jsonString)) {
            return null;
        }
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, clazz);
        try {
            return objectMapper.readValue(jsonString, javaType);
        } catch (Exception e) {
            log.error("from json happen err", e);
            return null;
        }
    }

    /**
     * 构建javaType
     */
    public static JavaType javaType(Class<?> parametrized, Class<?>... parameterClasses) {
        return objectMapper.getTypeFactory().constructParametricType(parametrized, parameterClasses);
    }

    public static JavaType javaType(Class<?> parametrized, JavaType... parameterClasses) {
        return objectMapper.getTypeFactory().constructParametricType(parametrized, parameterClasses);
    }

    public static <T> ParameterizedTypeReference<T> reference(Class<?> parametrized, Class<?>... parameterClasses) {
        return ParameterizedTypeReference.forType(javaType(parametrized, parameterClasses));
    }

    public static <T> ParameterizedTypeReference<T> reference(Class<?> parametrized, JavaType... parameterClasses) {
        return ParameterizedTypeReference.forType(javaType(parametrized, parameterClasses));
    }

    public static JavaType javaType(Type type) {
        return objectMapper.getTypeFactory().constructType(type);
    }
}
